Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 30 additions & 0 deletions docs/examples/objective-c.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
---
# Automatically generated from tests/objective-c/cmake.toml - DO NOT EDIT
layout: default
title: Objective-C
permalink: /examples/objective-c
parent: Examples
nav_order: 11
---

# Objective-C

Add Objective-C sources on Apple platforms:

```toml
[project]
name = "objective-c"
description = "Objective-C"
languages = ["C"]
apple.languages = ["OBJC"]

[target.hello]
type = "executable"
sources = ["src/main.c"]
apple.sources = ["src/apple.m"]
apple.link-libraries = ["$<LINK_LIBRARY:FRAMEWORK,Foundation>"]
```



<sup><sub>This page was automatically generated from [tests/objective-c/cmake.toml](https://github.com/build-cpp/cmkr/tree/main/tests/objective-c/cmake.toml).</sub></sup>
2 changes: 1 addition & 1 deletion include/project_parser.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -194,7 +194,7 @@ struct Project {
std::string project_name;
std::string project_version;
std::string project_description;
std::vector<std::string> project_languages;
ConditionVector project_languages;
bool project_allow_unknown_languages = false;
MsvcRuntimeType project_msvc_runtime = msvc_last;
Condition<std::string> cmake_before;
Expand Down
79 changes: 44 additions & 35 deletions src/cmake_generator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -725,16 +725,41 @@ void generate_cmake(const char *path, const parser::Project *parent_project) {

parser::Project project(parent_project, path, false);

for (const auto &lang : project.project_languages) {
if (known_languages.find(lang) == known_languages.end()) {
tsl::ordered_set<std::string> flat_project_languages;
for (const auto &itr : project.project_languages) {
for (const auto &language : itr.second) {
flat_project_languages.insert(language);
}
}

// Reference: https://gitlab.kitware.com/cmake/cmake/-/issues/24340#note_1304703
flat_project_languages.insert("RC");

// All acceptable extensions based off our given languages.
tsl::ordered_set<std::string> project_extensions;
for (const auto &language : flat_project_languages) {
auto itr = known_languages.find(language);
if (itr == known_languages.end()) {
if (project.project_allow_unknown_languages) {
printf("[warning] Unknown language '%s' specified\n", lang.c_str());
printf("[warning] Unknown language '%s' specified\n", language.c_str());
} else {
throw std::runtime_error("Unknown language '" + lang + "' specified");
throw std::runtime_error("Unknown language '" + language + "' specified");
}
} else {
project_extensions.insert(itr->second.begin(), itr->second.end());
}
}

auto contains_language_source = [&project_extensions](const std::vector<std::string> &sources) {
for (const auto &source : sources) {
auto extension = fs::path(source).extension().string();
if (project_extensions.count(extension) > 0) {
return true;
}
}
return false;
};

Generator gen(project, path);

// Helper lambdas for more convenient CMake generation
Expand Down Expand Up @@ -912,17 +937,29 @@ void generate_cmake(const char *path, const parser::Project *parent_project) {
gen.conditional_cmake(project.cmake_before);

if (!project.project_name.empty()) {
auto languages = std::make_pair("LANGUAGES", project.project_languages);
auto languages = std::make_pair("LANGUAGES", project.project_languages[""]);
auto version = std::make_pair("VERSION", project.project_version);
auto description = std::make_pair("DESCRIPTION", project.project_description);
cmd("project")(project.project_name, languages, version, description).endl();
cmd("project")(project.project_name, languages, version, description);

for (const auto &language : project.project_languages) {
for (const auto &language : project.project_languages[""]) {
if (language == "CSharp") {
cmd("include")("CSharpUtilities").endl();
break;
}
}

gen.handle_condition(project.project_languages, [&cmd](const std::string &condition, const std::vector<std::string> &languages) {
if (!condition.empty()) {
cmd("enable_language")(languages).endl();
for (const auto &language : languages) {
if (language == "CSharp") {
cmd("include")("CSharpUtilities").endl();
break;
}
}
}
});
}

gen.conditional_includes(project.include_after);
Expand Down Expand Up @@ -1138,34 +1175,6 @@ void generate_cmake(const char *path, const parser::Project *parent_project) {
gen.conditional_cmake(subdir.cmake_after);
}

// The implicit default is ["C", "CXX"], so make sure this list isn't
// empty or projects without languages explicitly defined will error.
auto project_languages = project.project_languages;
if (project_languages.empty())
project_languages = {"C", "CXX"};

// Reference: https://gitlab.kitware.com/cmake/cmake/-/issues/24340#note_1304703
project_languages.push_back("RC");

// All acceptable extensions based off our given languages.
tsl::ordered_set<std::string> project_extensions;
for (const auto &language : project_languages) {
auto itr = known_languages.find(language);
if (itr != known_languages.end()) {
project_extensions.insert(itr->second.begin(), itr->second.end());
}
}

auto contains_language_source = [&project_extensions](const std::vector<std::string> &sources) {
for (const auto &source : sources) {
auto extension = fs::path(source).extension().string();
if (project_extensions.count(extension) > 0) {
return true;
}
}
return false;
};

if (!project.targets.empty()) {
auto project_root = project.root();
for (size_t i = 0; i < project.targets.size(); i++) {
Expand Down
5 changes: 5 additions & 0 deletions src/project_parser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -301,6 +301,11 @@ Project::Project(const Project *parent, const std::string &path, bool build) : p
project.required("name", project_name);
project.optional("version", project_version);
project.optional("description", project_description);

// The implicit default is ["C", "CXX"], so make sure this list isn't
// empty or projects without languages explicitly defined will error.
project_languages[""] = {"C", "CXX"};

project.optional("languages", project_languages);
project.optional("allow-unknown-languages", project_allow_unknown_languages);
project.optional("cmake-before", cmake_before);
Expand Down
9 changes: 9 additions & 0 deletions tests/CMakeLists.txt

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 6 additions & 0 deletions tests/cmake.toml
Original file line number Diff line number Diff line change
Expand Up @@ -65,3 +65,9 @@ name = "relative-paths"
working-directory = "relative-paths"
command = "$<TARGET_FILE:cmkr>"
arguments = ["build"]

[[test]]
name = "objective-c"
working-directory = "objective-c"
command = "$<TARGET_FILE:cmkr>"
arguments = ["build"]
13 changes: 13 additions & 0 deletions tests/objective-c/cmake.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# Add Objective-C sources on Apple platforms:

[project]
name = "objective-c"
description = "Objective-C"
languages = ["C"]
apple.languages = ["OBJC"]

[target.hello]
type = "executable"
sources = ["src/main.c"]
apple.sources = ["src/apple.m"]
apple.link-libraries = ["$<LINK_LIBRARY:FRAMEWORK,Foundation>"]
7 changes: 7 additions & 0 deletions tests/objective-c/src/apple.m
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
#import <Foundation/Foundation.h>

void platform_specific() {
NSFileHandle *stdout = [NSFileHandle fileHandleWithStandardOutput];
NSString *message = @"Hello from Objective-C!\n";
[stdout writeData:[message dataUsingEncoding:NSUTF8StringEncoding] error:nil];
}
14 changes: 14 additions & 0 deletions tests/objective-c/src/main.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
#include <stdio.h>

#ifdef __APPLE__
void platform_specific();
#else
void platform_specific() {
puts("This is not an Apple platform.");
}
#endif

int main() {
platform_specific();
return 0;
}