static bool link_lib(compile_t* c, const char* file_o) { size_t len = strlen(c->filename); #if defined(PLATFORM_IS_POSIX_BASED) VLA(char, libname, len + 4); memcpy(libname, "lib", 3); memcpy(libname + 3, c->filename, len + 1); const char* file_lib = suffix_filename(c->opt->output, libname, ".a"); printf("Archiving %s\n", file_lib); len = 32 + strlen(file_lib) + strlen(file_o); VLA(char, cmd, len); snprintf(cmd, len, "ar -rcs %s %s", file_lib, file_o); if(system(cmd) != 0) { errorf(NULL, "unable to link"); return false; } #elif defined(PLATFORM_IS_WINDOWS) VLA(char, libname, len + 1); memcpy(libname, c->filename, len + 1); const char* file_lib = suffix_filename(c->opt->output, libname, ".lib"); printf("Archiving %s\n", file_lib); vcvars_t vcvars; if(!vcvars_get(&vcvars)) { errorf(NULL, "unable to link"); return false; } len = 128 + strlen(file_lib) + strlen(file_o); VLA(char, cmd, len); snprintf(cmd, len, "cmd /C \"\"%s\" /NOLOGO /OUT:%s %s\"", vcvars.ar, file_lib, file_o); if(system(cmd) == -1) { errorf(NULL, "unable to link"); return false; } #endif return true; }
static bool link_lib(compile_t* c, const char* file_o) { #if defined(PLATFORM_IS_POSIX_BASED) const char* file_lib = suffix_filename(c->opt->output, "lib", c->filename, ".a"); printf("Archiving %s\n", file_lib); size_t len = 32 + strlen(file_lib) + strlen(file_o); char* cmd = (char*)pool_alloc_size(len); snprintf(cmd, len, "ar -rcs %s %s", file_lib, file_o); if(system(cmd) != 0) { errorf(NULL, "unable to link"); pool_free_size(len, cmd); return false; } pool_free_size(len, cmd); #elif defined(PLATFORM_IS_WINDOWS) const char* file_lib = suffix_filename(c->opt->output, "", c->filename, ".lib"); printf("Archiving %s\n", file_lib); vcvars_t vcvars; if(!vcvars_get(&vcvars)) { errorf(NULL, "unable to link"); return false; } size_t len = 128 + strlen(file_lib) + strlen(file_o); char* cmd = (char*)pool_alloc_size(len); snprintf(cmd, len, "cmd /C \"\"%s\" /NOLOGO /OUT:%s %s\"", vcvars.ar, file_lib, file_o); if(system(cmd) == -1) { errorf(NULL, "unable to link"); pool_free_size(len, cmd); return false; } pool_free_size(len, cmd); #endif return true; }
static bool link_lib(compile_t* c, const char* file_o) { errors_t* errors = c->opt->check.errors; #if defined(PLATFORM_IS_POSIX_BASED) const char* file_lib = suffix_filename(c, c->opt->output, "lib", c->filename, ".a"); if(c->opt->verbosity >= VERBOSITY_MINIMAL) fprintf(stderr, "Archiving %s\n", file_lib); size_t len = 32 + strlen(file_lib) + strlen(file_o); char* cmd = (char*)ponyint_pool_alloc_size(len); #if defined(PLATFORM_IS_MACOSX) snprintf(cmd, len, "/usr/bin/ar -rcs %s %s", file_lib, file_o); #else snprintf(cmd, len, "ar -rcs %s %s", file_lib, file_o); #endif if(c->opt->verbosity >= VERBOSITY_TOOL_INFO) fprintf(stderr, "%s\n", cmd); if(system(cmd) != 0) { errorf(errors, NULL, "unable to link: %s", cmd); ponyint_pool_free_size(len, cmd); return false; } ponyint_pool_free_size(len, cmd); #elif defined(PLATFORM_IS_WINDOWS) const char* file_lib = suffix_filename(c, c->opt->output, "", c->filename, ".lib"); if(c->opt->verbosity >= VERBOSITY_MINIMAL) fprintf(stderr, "Archiving %s\n", file_lib); vcvars_t vcvars; if(!vcvars_get(c, &vcvars, errors)) { errorf(errors, NULL, "unable to link: no vcvars"); return false; } size_t len = strlen(vcvars.ar) + strlen(file_lib) + strlen(file_o) + 64; char* cmd = (char*)ponyint_pool_alloc_size(len); snprintf(cmd, len, "cmd /C \"\"%s\" /NOLOGO /OUT:%s %s\"", vcvars.ar, file_lib, file_o); if(c->opt->verbosity >= VERBOSITY_TOOL_INFO) fprintf(stderr, "%s\n", cmd); if(system(cmd) == -1) { errorf(errors, NULL, "unable to link: %s", cmd); ponyint_pool_free_size(len, cmd); return false; } ponyint_pool_free_size(len, cmd); #endif return true; }
static bool link_exe(compile_t* c, ast_t* program, const char* file_o) { #if defined(PLATFORM_IS_MACOSX) char* arch = strchr(c->opt->triple, '-'); if(arch == NULL) { errorf(NULL, "couldn't determine architecture from %s", c->opt->triple); return false; } const char* file_exe = suffix_filename(c->opt->output, "", c->filename, ""); printf("Linking %s\n", file_exe); program_lib_build_args(program, "-L", "", "", "-l", ""); const char* lib_args = program_lib_args(program); size_t arch_len = arch - c->opt->triple; size_t ld_len = 128 + arch_len + strlen(file_exe) + strlen(file_o) + strlen(lib_args); char* ld_cmd = (char*)pool_alloc_size(ld_len); snprintf(ld_cmd, ld_len, "ld -execute -no_pie -dead_strip -arch %.*s -macosx_version_min 10.8 " "-o %s %s %s -lponyrt -lSystem", (int)arch_len, c->opt->triple, file_exe, file_o, lib_args ); if(system(ld_cmd) != 0) { errorf(NULL, "unable to link"); pool_free_size(ld_len, ld_cmd); return false; } pool_free_size(ld_len, ld_cmd); if(!c->opt->strip_debug) { size_t dsym_len = 16 + strlen(file_exe); char* dsym_cmd = (char*)pool_alloc_size(dsym_len); snprintf(dsym_cmd, dsym_len, "rm -rf %s.dSYM", file_exe); system(dsym_cmd); snprintf(dsym_cmd, dsym_len, "dsymutil %s", file_exe); if(system(dsym_cmd) != 0) errorf(NULL, "unable to create dsym"); pool_free_size(dsym_len, dsym_cmd); } #elif defined(PLATFORM_IS_LINUX) || defined(PLATFORM_IS_FREEBSD) const char* file_exe = suffix_filename(c->opt->output, "", c->filename, ""); printf("Linking %s\n", file_exe); #ifdef PLATFORM_IS_FREEBSD use_path(program, "/usr/local/lib", NULL, NULL); #endif program_lib_build_args(program, "-L", "--start-group ", "--end-group ", "-l", ""); const char* lib_args = program_lib_args(program); const char* crt_dir = crt_directory(); const char* gccs_dir = gccs_directory(); if((crt_dir == NULL) || (gccs_dir == NULL)) { errorf(NULL, "could not find CRT"); return false; } size_t ld_len = 256 + strlen(file_exe) + strlen(file_o) + strlen(lib_args) + strlen(gccs_dir) + (3 * strlen(crt_dir)); char* ld_cmd = (char*)pool_alloc_size(ld_len); snprintf(ld_cmd, ld_len, "ld --eh-frame-hdr --hash-style=gnu " #if defined(PLATFORM_IS_LINUX) "-m elf_x86_64 -dynamic-linker /lib64/ld-linux-x86-64.so.2 " #elif defined(PLATFORM_IS_FREEBSD) "-m elf_x86_64_fbsd " #endif "-o %s %scrt1.o %scrti.o %s %s -lponyrt -lpthread " #ifdef PLATFORM_IS_LINUX "-ldl " #endif "-lm -lc %slibgcc_s.so.1 %scrtn.o", file_exe, crt_dir, crt_dir, file_o, lib_args, gccs_dir, crt_dir ); if(system(ld_cmd) != 0) { errorf(NULL, "unable to link"); pool_free_size(ld_len, ld_cmd); return false; } pool_free_size(ld_len, ld_cmd); #elif defined(PLATFORM_IS_WINDOWS) vcvars_t vcvars; if(!vcvars_get(&vcvars)) { errorf(NULL, "unable to link"); return false; } const char* file_exe = suffix_filename(c->opt->output, "", c->filename, ".exe"); printf("Linking %s\n", file_exe); program_lib_build_args(program, "/LIBPATH:", "", "", "", ".lib"); const char* lib_args = program_lib_args(program); size_t ld_len = 256 + strlen(file_exe) + strlen(file_o) + strlen(vcvars.kernel32) + strlen(vcvars.msvcrt) + strlen(lib_args); char* ld_cmd = (char*)pool_alloc_size(ld_len); snprintf(ld_cmd, ld_len, "cmd /C \"\"%s\" /DEBUG /NOLOGO /MACHINE:X64 " "/OUT:%s " "%s " "/LIBPATH:\"%s\" " "/LIBPATH:\"%s\" " "%s ponyrt.lib kernel32.lib msvcrt.lib Ws2_32.lib \"", vcvars.link, file_exe, file_o, vcvars.kernel32, vcvars.msvcrt, lib_args ); if(system(ld_cmd) == -1) { errorf(NULL, "unable to link"); pool_free_size(ld_len, ld_cmd); return false; } pool_free_size(ld_len, ld_cmd); #endif return true; }
static bool link_exe(compile_t* c, ast_t* program, const char* file_o) { errors_t* errors = c->opt->check.errors; const char* ponyrt = c->opt->runtimebc ? "" : #if defined(PLATFORM_IS_WINDOWS) "ponyrt.lib"; #elif defined(PLATFORM_IS_LINUX) c->opt->pic ? "-lponyrt-pic" : "-lponyrt"; #else "-lponyrt"; #endif #if defined(PLATFORM_IS_MACOSX) char* arch = strchr(c->opt->triple, '-'); if(arch == NULL) { errorf(errors, NULL, "couldn't determine architecture from %s", c->opt->triple); return false; } const char* file_exe = suffix_filename(c, c->opt->output, "", c->filename, ""); if(c->opt->verbosity >= VERBOSITY_MINIMAL) fprintf(stderr, "Linking %s\n", file_exe); program_lib_build_args(program, c->opt, "-L", NULL, "", "", "-l", ""); const char* lib_args = program_lib_args(program); size_t arch_len = arch - c->opt->triple; size_t ld_len = 128 + arch_len + strlen(file_exe) + strlen(file_o) + strlen(lib_args); char* ld_cmd = (char*)ponyint_pool_alloc_size(ld_len); const char* linker = c->opt->linker != NULL ? c->opt->linker : "ld"; snprintf(ld_cmd, ld_len, "%s -execute -no_pie -dead_strip -arch %.*s " "-macosx_version_min 10.8 -o %s %s %s %s -lSystem", linker, (int)arch_len, c->opt->triple, file_exe, file_o, lib_args, ponyrt ); if(c->opt->verbosity >= VERBOSITY_TOOL_INFO) fprintf(stderr, "%s\n", ld_cmd); if(system(ld_cmd) != 0) { errorf(errors, NULL, "unable to link: %s", ld_cmd); ponyint_pool_free_size(ld_len, ld_cmd); return false; } ponyint_pool_free_size(ld_len, ld_cmd); if(!c->opt->strip_debug) { size_t dsym_len = 16 + strlen(file_exe); char* dsym_cmd = (char*)ponyint_pool_alloc_size(dsym_len); snprintf(dsym_cmd, dsym_len, "rm -rf %s.dSYM", file_exe); system(dsym_cmd); snprintf(dsym_cmd, dsym_len, "dsymutil %s", file_exe); if(system(dsym_cmd) != 0) errorf(errors, NULL, "unable to create dsym"); ponyint_pool_free_size(dsym_len, dsym_cmd); } #elif defined(PLATFORM_IS_LINUX) || defined(PLATFORM_IS_FREEBSD) const char* file_exe = suffix_filename(c, c->opt->output, "", c->filename, ""); if(c->opt->verbosity >= VERBOSITY_MINIMAL) fprintf(stderr, "Linking %s\n", file_exe); program_lib_build_args(program, c->opt, "-L", "-Wl,-rpath,", "-Wl,--start-group ", "-Wl,--end-group ", "-l", ""); const char* lib_args = program_lib_args(program); const char* arch = c->opt->link_arch != NULL ? c->opt->link_arch : PONY_ARCH; bool fallback_linker = false; const char* linker = c->opt->linker != NULL ? c->opt->linker : env_cc_or_pony_compiler(&fallback_linker); if((c->opt->verbosity >= VERBOSITY_MINIMAL) && fallback_linker) { fprintf(stderr, "Warning: environment variable $CC undefined, using %s as the linker\n", PONY_COMPILER); } const char* mcx16_arg = target_is_ilp32(c->opt->triple) ? "" : "-mcx16"; const char* fuseld = target_is_linux(c->opt->triple) ? "-fuse-ld=gold " : ""; const char* ldl = target_is_linux(c->opt->triple) ? "-ldl " : ""; size_t ld_len = 512 + strlen(file_exe) + strlen(file_o) + strlen(lib_args) + strlen(arch) + strlen(mcx16_arg) + strlen(fuseld) + strlen(ldl); char* ld_cmd = (char*)ponyint_pool_alloc_size(ld_len); snprintf(ld_cmd, ld_len, "%s -o %s -O3 -march=%s " "%s " #ifdef PONY_USE_LTO "-flto -fuse-linker-plugin " #endif "%s %s %s %s -lpthread %s " "-lm", linker, file_exe, arch, mcx16_arg, fuseld, file_o, lib_args, ponyrt, ldl ); if(c->opt->verbosity >= VERBOSITY_TOOL_INFO) fprintf(stderr, "%s\n", ld_cmd); if(system(ld_cmd) != 0) { errorf(errors, NULL, "unable to link: %s", ld_cmd); ponyint_pool_free_size(ld_len, ld_cmd); return false; } ponyint_pool_free_size(ld_len, ld_cmd); #elif defined(PLATFORM_IS_WINDOWS) vcvars_t vcvars; if(!vcvars_get(&vcvars, errors)) { errorf(errors, NULL, "unable to link: no vcvars"); return false; } const char* file_exe = suffix_filename(c, c->opt->output, "", c->filename, ".exe"); if(c->opt->verbosity >= VERBOSITY_MINIMAL) fprintf(stderr, "Linking %s\n", file_exe); program_lib_build_args(program, c->opt, "/LIBPATH:", NULL, "", "", "", ".lib"); const char* lib_args = program_lib_args(program); char ucrt_lib[MAX_PATH + 12]; if (strlen(vcvars.ucrt) > 0) snprintf(ucrt_lib, MAX_PATH + 12, "/LIBPATH:\"%s\"", vcvars.ucrt); else ucrt_lib[0] = '\0'; size_t ld_len = 256 + strlen(file_exe) + strlen(file_o) + strlen(vcvars.kernel32) + strlen(vcvars.msvcrt) + strlen(lib_args); char* ld_cmd = (char*)ponyint_pool_alloc_size(ld_len); while (true) { int num_written = snprintf(ld_cmd, ld_len, "cmd /C \"\"%s\" /DEBUG /NOLOGO /MACHINE:X64 " "/OUT:%s " "%s %s " "/LIBPATH:\"%s\" " "/LIBPATH:\"%s\" " "%s %s %s \"", vcvars.link, file_exe, file_o, ucrt_lib, vcvars.kernel32, vcvars.msvcrt, lib_args, vcvars.default_libs, ponyrt ); if (num_written < ld_len) break; ponyint_pool_free_size(ld_len, ld_cmd); ld_len += 256; ld_cmd = (char*)ponyint_pool_alloc_size(ld_len); } if(c->opt->verbosity >= VERBOSITY_TOOL_INFO) fprintf(stderr, "%s\n", ld_cmd); if (system(ld_cmd) == -1) { errorf(errors, NULL, "unable to link: %s", ld_cmd); ponyint_pool_free_size(ld_len, ld_cmd); return false; } ponyint_pool_free_size(ld_len, ld_cmd); #endif return true; }
static bool link_exe(compile_t* c, ast_t* program, const char* file_o) { errors_t* errors = c->opt->check.errors; #if defined(PLATFORM_IS_MACOSX) char* arch = strchr(c->opt->triple, '-'); if(arch == NULL) { errorf(errors, NULL, "couldn't determine architecture from %s", c->opt->triple); return false; } const char* file_exe = suffix_filename(c, c->opt->output, "", c->filename, ""); if(c->opt->verbosity >= VERBOSITY_MINIMAL) fprintf(stderr, "Linking %s\n", file_exe); program_lib_build_args(program, c->opt, "-L", NULL, "", "", "-l", ""); const char* lib_args = program_lib_args(program); size_t arch_len = arch - c->opt->triple; size_t ld_len = 128 + arch_len + strlen(file_exe) + strlen(file_o) + strlen(lib_args); char* ld_cmd = (char*)ponyint_pool_alloc_size(ld_len); // Avoid incorrect ld, eg from macports. snprintf(ld_cmd, ld_len, "/usr/bin/ld -execute -no_pie -dead_strip -arch %.*s " "-macosx_version_min 10.8 -o %s %s %s -lponyrt -lSystem", (int)arch_len, c->opt->triple, file_exe, file_o, lib_args ); if(c->opt->verbosity >= VERBOSITY_TOOL_INFO) fprintf(stderr, "%s\n", ld_cmd); if(system(ld_cmd) != 0) { errorf(errors, NULL, "unable to link: %s", ld_cmd); ponyint_pool_free_size(ld_len, ld_cmd); return false; } ponyint_pool_free_size(ld_len, ld_cmd); if(!c->opt->strip_debug) { size_t dsym_len = 16 + strlen(file_exe); char* dsym_cmd = (char*)ponyint_pool_alloc_size(dsym_len); snprintf(dsym_cmd, dsym_len, "rm -rf %s.dSYM", file_exe); system(dsym_cmd); snprintf(dsym_cmd, dsym_len, "dsymutil %s", file_exe); if(system(dsym_cmd) != 0) errorf(errors, NULL, "unable to create dsym"); ponyint_pool_free_size(dsym_len, dsym_cmd); } #elif defined(PLATFORM_IS_LINUX) || defined(PLATFORM_IS_FREEBSD) const char* file_exe = suffix_filename(c, c->opt->output, "", c->filename, ""); if(c->opt->verbosity >= VERBOSITY_MINIMAL) fprintf(stderr, "Linking %s\n", file_exe); program_lib_build_args(program, c->opt, "-L", "-Wl,-rpath,", "-Wl,--start-group ", "-Wl,--end-group ", "-l", ""); const char* lib_args = program_lib_args(program); size_t ld_len = 512 + strlen(file_exe) + strlen(file_o) + strlen(lib_args); char* ld_cmd = (char*)ponyint_pool_alloc_size(ld_len); snprintf(ld_cmd, ld_len, PONY_COMPILER " -o %s -O3 -march=" PONY_ARCH " " #ifndef PLATFORM_IS_ILP32 "-mcx16 " #endif #ifdef PONY_USE_LTO "-flto -fuse-linker-plugin " #endif #ifdef PLATFORM_IS_LINUX "-fuse-ld=gold " #endif "%s %s -lponyrt -lpthread " #ifdef PLATFORM_IS_LINUX "-ldl " #endif "-lm", file_exe, file_o, lib_args ); if(c->opt->verbosity >= VERBOSITY_TOOL_INFO) fprintf(stderr, "%s\n", ld_cmd); if(system(ld_cmd) != 0) { errorf(errors, NULL, "unable to link: %s", ld_cmd); ponyint_pool_free_size(ld_len, ld_cmd); return false; } ponyint_pool_free_size(ld_len, ld_cmd); #elif defined(PLATFORM_IS_WINDOWS) vcvars_t vcvars; if(!vcvars_get(&vcvars, errors)) { errorf(errors, NULL, "unable to link: no vcvars"); return false; } const char* file_exe = suffix_filename(c, c->opt->output, "", c->filename, ".exe"); if(c->opt->verbosity >= VERBOSITY_MINIMAL) fprintf(stderr, "Linking %s\n", file_exe); program_lib_build_args(program, c->opt, "/LIBPATH:", NULL, "", "", "", ".lib"); const char* lib_args = program_lib_args(program); size_t ld_len = 256 + strlen(file_exe) + strlen(file_o) + strlen(vcvars.kernel32) + strlen(vcvars.msvcrt) + strlen(lib_args); char* ld_cmd = (char*)ponyint_pool_alloc_size(ld_len); while (true) { int num_written = snprintf(ld_cmd, ld_len, "cmd /C \"\"%s\" /DEBUG /NOLOGO /MACHINE:X64 " "/OUT:%s " "%s " "/LIBPATH:\"%s\" " "/LIBPATH:\"%s\" " "%s kernel32.lib msvcrt.lib Ws2_32.lib vcruntime.lib legacy_stdio_definitions.lib ponyrt.lib \"", vcvars.link, file_exe, file_o, vcvars.kernel32, vcvars.msvcrt, lib_args ); if (num_written < ld_len) break; ponyint_pool_free_size(ld_len, ld_cmd); ld_len += 256; ld_cmd = (char*)ponyint_pool_alloc_size(ld_len); } if(c->opt->verbosity >= VERBOSITY_TOOL_INFO) fprintf(stderr, "%s\n", ld_cmd); if (system(ld_cmd) == -1) { errorf(errors, NULL, "unable to link: %s", ld_cmd); ponyint_pool_free_size(ld_len, ld_cmd); return false; } ponyint_pool_free_size(ld_len, ld_cmd); #endif return true; }