From 0e469426dd799942376dd4ea96ea35ceae7f2cf8 Mon Sep 17 00:00:00 2001 From: Jussi Pakkanen Date: Fri, 15 Apr 2016 22:25:23 +0300 Subject: Created simple C project with own libc. --- test cases/ownstdlib/1 libc/libc.c | 35 +++++++++++++++++++++++++++++++++ test cases/ownstdlib/1 libc/meson.build | 18 +++++++++++++++++ test cases/ownstdlib/1 libc/prog.c | 7 +++++++ test cases/ownstdlib/1 libc/stdio.h | 5 +++++ test cases/ownstdlib/1 libc/stubstart.s | 8 ++++++++ 5 files changed, 73 insertions(+) create mode 100644 test cases/ownstdlib/1 libc/libc.c create mode 100644 test cases/ownstdlib/1 libc/meson.build create mode 100644 test cases/ownstdlib/1 libc/prog.c create mode 100644 test cases/ownstdlib/1 libc/stdio.h create mode 100644 test cases/ownstdlib/1 libc/stubstart.s diff --git a/test cases/ownstdlib/1 libc/libc.c b/test cases/ownstdlib/1 libc/libc.c new file mode 100644 index 0000000..67261cb --- /dev/null +++ b/test cases/ownstdlib/1 libc/libc.c @@ -0,0 +1,35 @@ +/* Do not use this as the basis of your own libc. + * The code is probably unoptimal or wonky, as I + * had no prior experience with this, but instead + * just fiddled with the code until it worked. + */ + +#include + +#define STDOUT 1 +#define SYS_WRITE 4 + +int simple_print(const char *msg, const long bufsize) { + int count; + long total_written = 0; + while(total_written < bufsize) { + asm( + "int $0x80\n\t" + : "=a"(count) + : "0"(SYS_WRITE), "b"(STDOUT), "c"(msg+total_written), "d"(bufsize-total_written) + :); + if(count == 0) { + return 1; + } + total_written += count; + } + return 0; +} + +int simple_strlen(const char *str) { + int len = 0; + while(str[len] != '\0') { + len++; + } + return len; +} diff --git a/test cases/ownstdlib/1 libc/meson.build b/test cases/ownstdlib/1 libc/meson.build new file mode 100644 index 0000000..1151926 --- /dev/null +++ b/test cases/ownstdlib/1 libc/meson.build @@ -0,0 +1,18 @@ +project('own libc', 'c') + +# A simple project that uses its own libc. + +# Start with manual flags to compile, then add platform support. + +libc = static_library('c', 'libc.c', 'stubstart.s', + c_args : '-nostdlib', + link_args : '-nostdlib', +) + +exe = executable('selfcontained', 'prog.c', + c_args : '-nostdlib', + link_args : '-nostdlib', + link_with : libc, +) + +test('standalone test', exe) diff --git a/test cases/ownstdlib/1 libc/prog.c b/test cases/ownstdlib/1 libc/prog.c new file mode 100644 index 0000000..9414bce --- /dev/null +++ b/test cases/ownstdlib/1 libc/prog.c @@ -0,0 +1,7 @@ + +#include + +int main() { + const char *message = "Hello without stdlib.\n"; + return simple_print(message, simple_strlen(message)); +} diff --git a/test cases/ownstdlib/1 libc/stdio.h b/test cases/ownstdlib/1 libc/stdio.h new file mode 100644 index 0000000..c3f8f56 --- /dev/null +++ b/test cases/ownstdlib/1 libc/stdio.h @@ -0,0 +1,5 @@ +#pragma once + +int simple_print(const char *msg, const long bufsize); + +int simple_strlen(const char *str); diff --git a/test cases/ownstdlib/1 libc/stubstart.s b/test cases/ownstdlib/1 libc/stubstart.s new file mode 100644 index 0000000..0a6d972 --- /dev/null +++ b/test cases/ownstdlib/1 libc/stubstart.s @@ -0,0 +1,8 @@ +.globl _start + +_start: + + call main + movl %eax, %ebx + movl $1, %eax + int $0x80 -- cgit v1.1 From 695aa0b8c28a0069d0e999aa039a60951b440ea4 Mon Sep 17 00:00:00 2001 From: Jussi Pakkanen Date: Sat, 21 May 2016 19:35:36 +0300 Subject: Made cstdlib a subproject. --- cross/ownstdlib.txt | 13 ++++++++ manual tests/9 nostdlib/meson.build | 14 +++++++++ manual tests/9 nostdlib/prog.c | 7 +++++ manual tests/9 nostdlib/subprojects/mylibc/libc.c | 35 ++++++++++++++++++++++ .../9 nostdlib/subprojects/mylibc/meson.build | 12 ++++++++ manual tests/9 nostdlib/subprojects/mylibc/stdio.h | 5 ++++ .../9 nostdlib/subprojects/mylibc/stubstart.s | 8 +++++ test cases/ownstdlib/1 libc/libc.c | 35 ---------------------- test cases/ownstdlib/1 libc/meson.build | 18 ----------- test cases/ownstdlib/1 libc/prog.c | 7 ----- test cases/ownstdlib/1 libc/stdio.h | 5 ---- test cases/ownstdlib/1 libc/stubstart.s | 8 ----- 12 files changed, 94 insertions(+), 73 deletions(-) create mode 100644 cross/ownstdlib.txt create mode 100644 manual tests/9 nostdlib/meson.build create mode 100644 manual tests/9 nostdlib/prog.c create mode 100644 manual tests/9 nostdlib/subprojects/mylibc/libc.c create mode 100644 manual tests/9 nostdlib/subprojects/mylibc/meson.build create mode 100644 manual tests/9 nostdlib/subprojects/mylibc/stdio.h create mode 100644 manual tests/9 nostdlib/subprojects/mylibc/stubstart.s delete mode 100644 test cases/ownstdlib/1 libc/libc.c delete mode 100644 test cases/ownstdlib/1 libc/meson.build delete mode 100644 test cases/ownstdlib/1 libc/prog.c delete mode 100644 test cases/ownstdlib/1 libc/stdio.h delete mode 100644 test cases/ownstdlib/1 libc/stubstart.s diff --git a/cross/ownstdlib.txt b/cross/ownstdlib.txt new file mode 100644 index 0000000..46e99f7 --- /dev/null +++ b/cross/ownstdlib.txt @@ -0,0 +1,13 @@ +# This is a setup for compiling a program that runs natively +# but uses a custom std lib. This test will only work on +# x86_64. + +[target_machine] +system = 'linux' +cpu_family = 'x86_64' +cpu = 'x86_64' +endian = 'little' + +[properties] + +c_stdlib = ['mylibc', 'mylibc_dep'] # Subproject name, dependency name diff --git a/manual tests/9 nostdlib/meson.build b/manual tests/9 nostdlib/meson.build new file mode 100644 index 0000000..ad5b7b9 --- /dev/null +++ b/manual tests/9 nostdlib/meson.build @@ -0,0 +1,14 @@ +project('own libc', 'c') + +# A simple project that uses its own libc. + +libc_proj = subproject('mylibc') +libc_dep = libc_proj.get_variable('mylibc_dep') + +exe = executable('selfcontained', 'prog.c', + c_args : '-nostdlib', + link_args : '-nostdlib', + dependencies : libc_dep, +) + +test('standalone test', exe) diff --git a/manual tests/9 nostdlib/prog.c b/manual tests/9 nostdlib/prog.c new file mode 100644 index 0000000..9414bce --- /dev/null +++ b/manual tests/9 nostdlib/prog.c @@ -0,0 +1,7 @@ + +#include + +int main() { + const char *message = "Hello without stdlib.\n"; + return simple_print(message, simple_strlen(message)); +} diff --git a/manual tests/9 nostdlib/subprojects/mylibc/libc.c b/manual tests/9 nostdlib/subprojects/mylibc/libc.c new file mode 100644 index 0000000..67261cb --- /dev/null +++ b/manual tests/9 nostdlib/subprojects/mylibc/libc.c @@ -0,0 +1,35 @@ +/* Do not use this as the basis of your own libc. + * The code is probably unoptimal or wonky, as I + * had no prior experience with this, but instead + * just fiddled with the code until it worked. + */ + +#include + +#define STDOUT 1 +#define SYS_WRITE 4 + +int simple_print(const char *msg, const long bufsize) { + int count; + long total_written = 0; + while(total_written < bufsize) { + asm( + "int $0x80\n\t" + : "=a"(count) + : "0"(SYS_WRITE), "b"(STDOUT), "c"(msg+total_written), "d"(bufsize-total_written) + :); + if(count == 0) { + return 1; + } + total_written += count; + } + return 0; +} + +int simple_strlen(const char *str) { + int len = 0; + while(str[len] != '\0') { + len++; + } + return len; +} diff --git a/manual tests/9 nostdlib/subprojects/mylibc/meson.build b/manual tests/9 nostdlib/subprojects/mylibc/meson.build new file mode 100644 index 0000000..9d1fed8 --- /dev/null +++ b/manual tests/9 nostdlib/subprojects/mylibc/meson.build @@ -0,0 +1,12 @@ +project('own libc', 'c') + +# A very simple libc implementation + +# Start with manual flags to compile, then add platform support. + +libc = static_library('c', 'libc.c', 'stubstart.s', +) + +mylibc_dep = declare_dependency(link_with : libc, + include_directories : include_directories('.') +) diff --git a/manual tests/9 nostdlib/subprojects/mylibc/stdio.h b/manual tests/9 nostdlib/subprojects/mylibc/stdio.h new file mode 100644 index 0000000..c3f8f56 --- /dev/null +++ b/manual tests/9 nostdlib/subprojects/mylibc/stdio.h @@ -0,0 +1,5 @@ +#pragma once + +int simple_print(const char *msg, const long bufsize); + +int simple_strlen(const char *str); diff --git a/manual tests/9 nostdlib/subprojects/mylibc/stubstart.s b/manual tests/9 nostdlib/subprojects/mylibc/stubstart.s new file mode 100644 index 0000000..0a6d972 --- /dev/null +++ b/manual tests/9 nostdlib/subprojects/mylibc/stubstart.s @@ -0,0 +1,8 @@ +.globl _start + +_start: + + call main + movl %eax, %ebx + movl $1, %eax + int $0x80 diff --git a/test cases/ownstdlib/1 libc/libc.c b/test cases/ownstdlib/1 libc/libc.c deleted file mode 100644 index 67261cb..0000000 --- a/test cases/ownstdlib/1 libc/libc.c +++ /dev/null @@ -1,35 +0,0 @@ -/* Do not use this as the basis of your own libc. - * The code is probably unoptimal or wonky, as I - * had no prior experience with this, but instead - * just fiddled with the code until it worked. - */ - -#include - -#define STDOUT 1 -#define SYS_WRITE 4 - -int simple_print(const char *msg, const long bufsize) { - int count; - long total_written = 0; - while(total_written < bufsize) { - asm( - "int $0x80\n\t" - : "=a"(count) - : "0"(SYS_WRITE), "b"(STDOUT), "c"(msg+total_written), "d"(bufsize-total_written) - :); - if(count == 0) { - return 1; - } - total_written += count; - } - return 0; -} - -int simple_strlen(const char *str) { - int len = 0; - while(str[len] != '\0') { - len++; - } - return len; -} diff --git a/test cases/ownstdlib/1 libc/meson.build b/test cases/ownstdlib/1 libc/meson.build deleted file mode 100644 index 1151926..0000000 --- a/test cases/ownstdlib/1 libc/meson.build +++ /dev/null @@ -1,18 +0,0 @@ -project('own libc', 'c') - -# A simple project that uses its own libc. - -# Start with manual flags to compile, then add platform support. - -libc = static_library('c', 'libc.c', 'stubstart.s', - c_args : '-nostdlib', - link_args : '-nostdlib', -) - -exe = executable('selfcontained', 'prog.c', - c_args : '-nostdlib', - link_args : '-nostdlib', - link_with : libc, -) - -test('standalone test', exe) diff --git a/test cases/ownstdlib/1 libc/prog.c b/test cases/ownstdlib/1 libc/prog.c deleted file mode 100644 index 9414bce..0000000 --- a/test cases/ownstdlib/1 libc/prog.c +++ /dev/null @@ -1,7 +0,0 @@ - -#include - -int main() { - const char *message = "Hello without stdlib.\n"; - return simple_print(message, simple_strlen(message)); -} diff --git a/test cases/ownstdlib/1 libc/stdio.h b/test cases/ownstdlib/1 libc/stdio.h deleted file mode 100644 index c3f8f56..0000000 --- a/test cases/ownstdlib/1 libc/stdio.h +++ /dev/null @@ -1,5 +0,0 @@ -#pragma once - -int simple_print(const char *msg, const long bufsize); - -int simple_strlen(const char *str); diff --git a/test cases/ownstdlib/1 libc/stubstart.s b/test cases/ownstdlib/1 libc/stubstart.s deleted file mode 100644 index 0a6d972..0000000 --- a/test cases/ownstdlib/1 libc/stubstart.s +++ /dev/null @@ -1,8 +0,0 @@ -.globl _start - -_start: - - call main - movl %eax, %ebx - movl $1, %eax - int $0x80 -- cgit v1.1 From afe7252476290ffb6d26a21bf4ceab9eecc7ca79 Mon Sep 17 00:00:00 2001 From: Jussi Pakkanen Date: Sat, 21 May 2016 21:46:03 +0300 Subject: Can specify a stdlib subproject that is used implicitly on all targets with said language. --- manual tests/9 nostdlib/meson.build | 12 +++----- .../9 nostdlib/subprojects/mylibc/meson.build | 5 ++-- mesonbuild/backend/backends.py | 1 + mesonbuild/backend/ninjabackend.py | 15 ++++++++++ mesonbuild/build.py | 1 + mesonbuild/compilers.py | 6 ++++ mesonbuild/environment.py | 6 ++++ mesonbuild/interpreter.py | 35 ++++++++++++++++++++++ 8 files changed, 70 insertions(+), 11 deletions(-) diff --git a/manual tests/9 nostdlib/meson.build b/manual tests/9 nostdlib/meson.build index ad5b7b9..3ef743e 100644 --- a/manual tests/9 nostdlib/meson.build +++ b/manual tests/9 nostdlib/meson.build @@ -2,13 +2,9 @@ project('own libc', 'c') # A simple project that uses its own libc. -libc_proj = subproject('mylibc') -libc_dep = libc_proj.get_variable('mylibc_dep') - -exe = executable('selfcontained', 'prog.c', - c_args : '-nostdlib', - link_args : '-nostdlib', - dependencies : libc_dep, -) +# Note that we don't need to specify anything, the flags to use +# stdlib come from the cross file. + +exe = executable('selfcontained', 'prog.c') test('standalone test', exe) diff --git a/manual tests/9 nostdlib/subprojects/mylibc/meson.build b/manual tests/9 nostdlib/subprojects/mylibc/meson.build index 9d1fed8..aa0184e 100644 --- a/manual tests/9 nostdlib/subprojects/mylibc/meson.build +++ b/manual tests/9 nostdlib/subprojects/mylibc/meson.build @@ -2,10 +2,9 @@ project('own libc', 'c') # A very simple libc implementation -# Start with manual flags to compile, then add platform support. +# Do not specify -nostdlib & co. They come from cross specifications. -libc = static_library('c', 'libc.c', 'stubstart.s', -) +libc = static_library('c', 'libc.c', 'stubstart.s') mylibc_dep = declare_dependency(link_with : libc, include_directories : include_directories('.') diff --git a/mesonbuild/backend/backends.py b/mesonbuild/backend/backends.py index ceb466b..29966b9 100644 --- a/mesonbuild/backend/backends.py +++ b/mesonbuild/backend/backends.py @@ -244,6 +244,7 @@ class Backend(): def generate_basic_compiler_args(self, target, compiler): commands = [] + commands += self.get_cross_stdlib_args(target, compiler) commands += compiler.get_always_args() commands += compiler.get_warn_args(self.environment.coredata.get_builtin_option('warning_level')) commands += compiler.get_option_compile_args(self.environment.coredata.compiler_options) diff --git a/mesonbuild/backend/ninjabackend.py b/mesonbuild/backend/ninjabackend.py index 201b2d1..ec07395 100644 --- a/mesonbuild/backend/ninjabackend.py +++ b/mesonbuild/backend/ninjabackend.py @@ -1427,6 +1427,13 @@ rule FORTRAN_DEP_HACK mod_files.append(os.path.join(dirname, mod_name)) return mod_files + def get_cross_stdlib_args(self, target, compiler): + if not target.is_cross: + return [] + if self.environment.cross_info.has_stdlib(compiler.language): + return [] + return compiler.get_no_stdinc_args() + def generate_single_compile(self, target, outfile, src, is_generated=False, header_deps=[], order_deps=[]): if(isinstance(src, str) and src.endswith('.h')): raise RuntimeError('Fug') @@ -1632,6 +1639,13 @@ rule FORTRAN_DEP_HACK elem.add_item('CROSS', '--cross-host=' + self.environment.cross_info.config['host_machine']['system']) elem.write(outfile) + def get_cross_stdlib_link_args(self, target, linker): + if isinstance(target, build.StaticLibrary) or not target.is_cross: + return [] + if not self.environment.cross_info.has_stdlib(linker.language): + return [] + return linker.get_no_stdlib_link_args() + def generate_link(self, target, outfile, outname, obj_list, linker, extra_args=[]): if isinstance(target, build.StaticLibrary): linker_base = 'STATIC' @@ -1645,6 +1659,7 @@ rule FORTRAN_DEP_HACK linker_rule = linker_base + crstr + '_LINKER' abspath = os.path.join(self.environment.get_build_dir(), target.subdir) commands = [] + commands += self.get_cross_stdlib_link_args(target, linker) commands += linker.get_linker_always_args() if not isinstance(target, build.StaticLibrary): commands += compilers.get_base_link_args(self.environment.coredata.base_options, diff --git a/mesonbuild/build.py b/mesonbuild/build.py index 63cdcf3..60b5ec0 100644 --- a/mesonbuild/build.py +++ b/mesonbuild/build.py @@ -102,6 +102,7 @@ class Build: self.install_dirs = [] self.dep_manifest_name = None self.dep_manifest = {} + self.cross_stdlibs = {} def has_language(self, language): for i in self.compilers: diff --git a/mesonbuild/compilers.py b/mesonbuild/compilers.py index 8dee468..c4e8f0d 100644 --- a/mesonbuild/compilers.py +++ b/mesonbuild/compilers.py @@ -311,6 +311,12 @@ class CCompiler(Compiler): def get_always_args(self): return [] + def get_no_stdinc_args(self): + return ['-nostdinc'] + + def get_no_stdlib_link_args(self): + return ['-nostdlib'] + def get_warn_args(self, level): return self.warn_args[level] diff --git a/mesonbuild/environment.py b/mesonbuild/environment.py index c4591b4..19594c8 100644 --- a/mesonbuild/environment.py +++ b/mesonbuild/environment.py @@ -716,6 +716,12 @@ class CrossBuildInfo(): def has_target(self): return 'target_machine' in self.config + def has_stdlib(self, language): + return language + '_stdlib' in self.config['properties'] + + def get_stdlib(self, language): + return self.config['properties'][language + '_stdlib'] + # Wehn compiling a cross compiler we use the native compiler for everything. # But not when cross compiling a cross compiler. def need_cross_compiler(self): diff --git a/mesonbuild/interpreter.py b/mesonbuild/interpreter.py index d6a3a3e..b83f4a3 100644 --- a/mesonbuild/interpreter.py +++ b/mesonbuild/interpreter.py @@ -1080,6 +1080,22 @@ class Interpreter(): if not isinstance(first, mparser.FunctionNode) or first.func_name != 'project': raise InvalidCode('First statement must be a call to project') + def check_cross_stdlibs(self): + if self.build.environment.is_cross_build(): + cross_info = self.build.environment.cross_info + for c in self.build.cross_compilers: + l = c.language + try: + di = mesonlib.stringlistify(cross_info.get_stdlib(l)) + if len(di) != 2: + raise InterpreterException('Stdlib definition for %s should have exactly two elements.' \ + % l) + projname, depname = di + subproj = self.do_subproject(projname, {}) + self.build.cross_stdlibs[l] = subproj.get_variable_method([depname], {}) + except KeyError as e: + pass + def run(self): self.evaluate_codeblock(self.ast) mlog.log('Build targets in project:', mlog.bold(str(len(self.build.targets)))) @@ -1422,6 +1438,8 @@ class Interpreter(): if 'vala' in langs: if not 'c' in langs: raise InterpreterException('Compiling Vala requires C. Add C to your project languages and rerun Meson.') + if not self.is_subproject(): + self.check_cross_stdlibs() @stringArgs def func_add_languages(self, node, args, kwargs): @@ -1991,11 +2009,28 @@ class Interpreter(): mlog.debug('Unknown target type:', str(targetholder)) raise RuntimeError('Unreachable code') target = targetclass(name, self.subdir, self.subproject, is_cross, sources, objs, self.environment, kwargs) + if is_cross: + self.add_cross_stdlib_info(target) l = targetholder(target, self) self.add_target(name, l.held_object) self.global_args_frozen = True return l + def get_used_languages(self, target): + result = {} + for i in target.sources: + for c in self.build.compilers: + if c.can_compile(i): + result[c.language] = True + break + return result + + def add_cross_stdlib_info(self, target): + for l in self.get_used_languages(target): + if self.environment.cross_info.has_stdlib(l) and \ + self.subproject != self.environment.cross_info.get_stdlib(l)[0]: + target.add_external_deps(self.build.cross_stdlibs[l]) + def check_sources_exist(self, subdir, sources): for s in sources: if not isinstance(s, str): -- cgit v1.1