blob: 919365dc057a63fa5d6d717d1d2f6a448a1384a9 [file] [log] [blame]
/* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/* Source fragment for the Charmonizer tests' charmonizer.c.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "Charmonizer/Probe.h"
#include "Charmonizer/Probe/AtomicOps.h"
#include "Charmonizer/Probe/DirManip.h"
#include "Charmonizer/Probe/Floats.h"
#include "Charmonizer/Probe/FuncMacro.h"
#include "Charmonizer/Probe/Headers.h"
#include "Charmonizer/Probe/Booleans.h"
#include "Charmonizer/Probe/Integers.h"
#include "Charmonizer/Probe/LargeFiles.h"
#include "Charmonizer/Probe/Memory.h"
#include "Charmonizer/Probe/SymbolVisibility.h"
#include "Charmonizer/Probe/UnusedVars.h"
#include "Charmonizer/Probe/VariadicMacros.h"
#include "Charmonizer/Core/CLI.h"
#include "Charmonizer/Core/Compiler.h"
#include "Charmonizer/Core/ConfWriter.h"
#include "Charmonizer/Core/ConfWriterC.h"
#include "Charmonizer/Core/ConfWriterPerl.h"
#include "Charmonizer/Core/ConfWriterRuby.h"
#include "Charmonizer/Core/HeaderChecker.h"
#include "Charmonizer/Core/Make.h"
#include "Charmonizer/Core/OperatingSystem.h"
#include "Charmonizer/Core/Util.h"
typedef struct SourceFileContext {
chaz_MakeVar *var;
} SourceFileContext;
static const char chaztest_version[] = "0.1.0";
static const char chaztest_major_version[] = "0.1";
static void
S_write_makefile(void);
static void
S_c_file_callback(const char *dir, char *file, void *context);
static int
S_ends_with(const char *string, const char *postfix);
int main(int argc, const char **argv) {
/* Initialize. */
{
chaz_CLI *cli = chaz_CLI_new(argv[0], NULL);
int result = chaz_Probe_parse_cli_args(argc, argv, cli);
if (!result) {
fprintf(stderr, "%s", chaz_CLI_help(cli));
exit(1);
}
chaz_Probe_init(cli);
chaz_CLI_destroy(cli);
}
/* Run probe modules. */
chaz_DirManip_run();
chaz_Headers_run();
chaz_AtomicOps_run();
chaz_FuncMacro_run();
chaz_Booleans_run();
chaz_Integers_run();
chaz_Floats_run();
chaz_LargeFiles_run();
chaz_Memory_run();
chaz_SymbolVisibility_run();
chaz_UnusedVars_run();
chaz_VariadicMacros_run();
/* Create Makefile. */
S_write_makefile();
/* Write custom postamble. */
chaz_ConfWriter_append_conf(
"#ifdef CHY_HAS_SYS_TYPES_H\n"
" #include <sys/types.h>\n"
"#endif\n\n"
);
chaz_ConfWriter_append_conf(
"#ifdef CHY_HAS_ALLOCA_H\n"
" #include <alloca.h>\n"
"#elif defined(CHY_HAS_MALLOC_H)\n"
" #include <malloc.h>\n"
"#elif defined(CHY_ALLOCA_IN_STDLIB_H)\n"
" #include <stdlib.h>\n"
"#endif\n\n"
);
chaz_ConfWriter_append_conf(
"#ifdef CHY_HAS_WINDOWS_H\n"
" /* Target Windows XP. */\n"
" #ifndef WINVER\n"
" #define WINVER 0x0500\n"
" #endif\n"
" #ifndef _WIN32_WINNT\n"
" #define _WIN32_WINNT 0x0500\n"
" #endif\n"
"#endif\n\n"
);
/* Clean up. */
chaz_Probe_clean_up();
return 0;
}
static void
S_write_makefile() {
SourceFileContext sfc;
chaz_MakeFile *makefile;
chaz_MakeVar *var;
chaz_MakeRule *rule;
chaz_Lib *shared_lib;
chaz_CFlags *cflags;
const char *dir_sep = chaz_OS_dir_sep();
const char *exe_ext = chaz_OS_exe_ext();
char *shared_lib_filename;
char *test_exe;
char *scratch;
makefile = chaz_MakeFile_new();
/* Compiler flags. */
cflags = chaz_CC_new_cflags();
if (chaz_Probe_gcc_version_num()) {
chaz_CFlags_add_define(cflags, "_LARGEFILE64_SOURCE", NULL);
}
chaz_CFlags_add_include_dir(cflags, ".");
chaz_CFlags_add_include_dir(cflags, "src");
var = chaz_MakeFile_add_var(makefile, "CFLAGS", NULL);
chaz_MakeVar_append(var, chaz_CFlags_get_string(cflags));
chaz_MakeVar_append(var, chaz_CC_get_cflags());
chaz_CFlags_destroy(cflags);
/* Object files. */
sfc.var = chaz_MakeFile_add_var(makefile, "OBJECTS", NULL);
chaz_Make_list_files("src", "c", S_c_file_callback, &sfc);
/* Shared library. */
shared_lib = chaz_Lib_new("chaztest", chaz_Lib_SHARED, chaztest_version,
chaztest_major_version);
shared_lib_filename = chaz_Lib_filename(shared_lib);
/* 'all' target. */
chaz_MakeFile_add_rule(makefile, "all", shared_lib_filename);
/* Rule for shared library. */
chaz_MakeFile_add_shared_lib(makefile, shared_lib, "$(OBJECTS)", NULL);
/* Rule for test executable. */
test_exe = chaz_Util_join("", "tests", dir_sep, "test", exe_ext, NULL);
scratch = chaz_Util_join(dir_sep, "tests", "test.c", NULL);
cflags = chaz_CC_new_cflags();
chaz_CFlags_add_include_dir(cflags, "src");
chaz_CFlags_add_library(cflags, shared_lib);
rule = chaz_MakeFile_add_compiled_exe(makefile, test_exe, scratch, cflags);
chaz_MakeRule_add_prereq(rule, shared_lib_filename);
free(scratch);
chaz_CFlags_destroy(cflags);
/* 'test' target. */
rule = chaz_MakeFile_add_rule(makefile, "test", test_exe);
if (strcmp(chaz_OS_shared_lib_ext(), ".so") == 0) {
scratch = chaz_Util_join(" ", "LD_LIBRARY_PATH=.", test_exe, NULL);
}
else {
scratch = chaz_Util_strdup(test_exe);
}
chaz_MakeRule_add_command(rule, scratch);
free(scratch);
/* 'clean' target. */
rule = chaz_MakeFile_clean_rule(makefile);
chaz_MakeRule_add_rm_command(rule, "$(OBJECTS)");
/* Write Makefile. */
chaz_MakeFile_write(makefile);
/* Clean up. */
chaz_Lib_destroy(shared_lib);
chaz_MakeFile_destroy(makefile);
free(shared_lib_filename);
free(test_exe);
}
static void
S_c_file_callback(const char *dir, char *file, void *context) {
SourceFileContext *sfc = (SourceFileContext*)context;
const char *dir_sep = chaz_OS_dir_sep();
const char *obj_ext = chaz_CC_obj_ext();
size_t file_len = strlen(file);
char *obj_file;
/* Strip extension */
if (!S_ends_with(file, ".c")) {
chaz_Util_die("Unexpected C filename: %s", file);
}
file[file_len-2] = '\0';
obj_file = chaz_Util_join("", "src", dir_sep, file, obj_ext, NULL);
chaz_MakeVar_append(sfc->var, obj_file);
free(obj_file);
}
static int
S_ends_with(const char *string, const char *postfix) {
size_t len = strlen(string);
size_t postfix_len = strlen(postfix);
return len >= postfix_len
&& memcmp(string + len - postfix_len, postfix, postfix_len) == 0;
}