Skip to content
Open
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
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
cmake_minimum_required(VERSION 3.15)
project(cpp-optparse LANGUAGES CXX)

include(GNUInstallDirs)

add_library(OptionParser ${CPP_OPTPARSE_SRC_DIR}/OptionParser.cpp)
set_target_properties(OptionParser PROPERTIES WINDOWS_EXPORT_ALL_SYMBOLS TRUE)

install(TARGETS OptionParser
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[P1] lib vs lib64 install-layout mismatch can break linking

CMakeLists.txt installs via include(GNUInstallDirs) using ${CMAKE_INSTALL_LIBDIR} (lines 4, 11-12), which resolves to lib64 on many 64-bit distros (RHEL/Fedora/openSUSE). But the build metadata (-L.../lib, line 80) and the test link flags (-L.../lib, line 101) — plus the shared-build LD_LIBRARY_PATH/DYLD_LIBRARY_PATH (lines 113-114) — hardcode lib. On a lib64 platform the archive/library installs to lib64 while consumers search lib, producing link/runtime failures.

The json-c formula avoids exactly this by forcing c.define "CMAKE_INSTALL_LIBDIR", "lib" with an explicit comment. Since this formula ships its own CMakeLists.txt, the simplest fix is to set CMAKE_INSTALL_LIBDIR=lib in the CMake invocation (or drop GNUInstallDirs and hardcode lib/include/bin destinations).

ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR})

install(FILES ${CPP_OPTPARSE_SRC_DIR}/OptionParser.h DESTINATION ${CMAKE_INSTALL_INCLUDEDIR})
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
import (
"os"
"path/filepath"
"slices"
)

const consumerSource = `#include <string>
#include <vector>

#include "OptionParser.h"

using optparse::OptionParser;
using namespace std;

int main(int argc, char *argv[])
{
OptionParser parser = OptionParser() .description("just an example");

parser.add_option("-f", "--file") .dest("filename")
.help("write report to FILE") .metavar("FILE");
parser.add_option("-q", "--quiet")
.action("store_false") .dest("verbose") .set_default("1")
.help("don't print status messages to stdout");

optparse::Values options = parser.parse_args(argc, argv);
vector<string> args = parser.args();

if (options.get("verbose"))
cout << options["filename"] << endl;
}
`

// Conan Center cci.20171104 pins weisslj/cpp-optparse to this untagged commit.
id "weisslj/cpp-optparse"

fromVer "2ec0b7aca9a692ff93017ed44ca9d13a8e7d4d00"

defaults {
"shared": "OFF",
"fPIC": "ON",
}

filter => {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[P2] filter accepts contradictory fPIC=OFF + shared=ON combination

defaults declares both shared and fPIC (lines 39-42) and filter accepts any independent ON/OFF combination. In the Conan model fPIC is dropped when shared=True (shared implies PIC). Here fPIC=OFF + shared=ON is accepted and passes CMAKE_POSITION_INDEPENDENT_CODE=OFF to a shared build, producing a redundant/contradictory variant that either fails or is silently overridden. Consider normalizing (force fPIC when shared) or documenting that the combination is intentionally allowed.

for name, values in target.options {
if name != "shared" && name != "fPIC" {
return false
}
for value in values {
if value != "ON" && value != "OFF" {
return false
}
}
}
return true
}

onBuild ctx => {
installDir := ctx.outputDir

cmakeLists := ctx.Proj.readFile("2ec0b7aca9a692ff93017ed44ca9d13a8e7d4d00/CMakeLists.txt")!

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[P3] Comment density below repo convention

The reference formulas (cglm, json-c) document their build contract, option semantics, and why flags/build files are derived a certain way. This formula has a single comment. Two behaviors in particular would benefit from a short note consistent with convention: why a CMakeLists.txt is injected into the source tree (upstream ships no CMake build — the reason for vendoring one, line 61-62), and the shared/fPIC defaults reasoning (lines 39-42). Non-blocking.

os.writeFile(filepath.join(ctx.SourceDir, "CMakeLists.txt"), cmakeLists, 0o644)!

shared := slices.contains(target.options["shared"], "ON")
fPIC := slices.contains(target.options["fPIC"], "ON")
c := cmake.new(ctx.SourceDir, filepath.join(ctx.SourceDir, "_build"), installDir)
c.define "CPP_OPTPARSE_SRC_DIR", ctx.SourceDir
// pkgconfig.use searches the installed lib/pkgconfig directory.
c.define "CMAKE_INSTALL_LIBDIR", "lib"
c.defineBool "BUILD_SHARED_LIBS", shared
c.defineBool "CMAKE_POSITION_INDEPENDENT_CODE", fPIC
c.configure
c.build
c.install

licenseDir := filepath.join(installDir, "licenses")
os.mkdirAll(licenseDir, 0o755)!
os.writeFile(filepath.join(licenseDir, "LICENSE"), os.readFile(filepath.join(ctx.SourceDir, "LICENSE"))!, 0o644)!

libs := "-L$${libdir} -lOptionParser"
if slices.contains(target.require["os"], "linux") || slices.contains(target.require["os"], "freebsd") {
libs += " -lm"
}
Comment on lines +80 to +82

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[P2] -lm is appended but cpp-optparse has no libm dependency

-lm is added on Linux/FreeBSD in both onBuild (lines 83-85) and onTest (lines 104-106), but cpp-optparse uses no libm functions — OptionParser.{h,cpp} at this commit only pull in <string>, <vector>, <iostream>, <sstream>, etc., with no pow/sqrt/floor/log. This is harmless (the linker ignores an unneeded -lm) but misleading, and it diverges from repo convention: the cglm and json-c formulas justify their -lm against a real math dependency in comments. Consider dropping -lm, or adding a short comment explaining why it is retained for parity.

pcDir := filepath.join(installDir, "lib", "pkgconfig")
os.mkdirAll(pcDir, 0o755)!
pc := `prefix=$${pcfiledir}/../..
exec_prefix=$${prefix}
libdir=$${prefix}/lib
includedir=$${prefix}/include

Name: cpp-optparse
Description: Python's excellent OptionParser in C++
Version: 2ec0b7aca9a692ff93017ed44ca9d13a8e7d4d00
Libs: ` + libs + `
Cflags: -I$${includedir}
`
os.writeFile(filepath.join(pcDir, "cpp-optparse.pc"), []byte(pc), 0o644)!

pkgconfig.use installDir
ctx.setMetadata pkgconfig.lookup("cpp-optparse")!
}

onTest ctx => {
installDir := ctx.outputDir
testDir := filepath.join(ctx.SourceDir, "_llar_consumer")
testBuild := filepath.join(testDir, "_build")
sourcePath := filepath.join(testDir, "consumer.cpp")
binary := filepath.join(testBuild, "consumer")
os.mkdirAll(testBuild, 0o755)!
os.writeFile(sourcePath, []byte(consumerSource), 0o644)!

pkgconfig.use installDir
flagsFile := filepath.join(testDir, "cpp-optparse.flags")
os.writeFile(flagsFile, []byte(pkgconfig.lookup("cpp-optparse")!), 0o644)!
exec! "c++", sourcePath, "-o", binary, "@"+flagsFile

if slices.contains(target.options["shared"], "ON") {
os.setenv("LD_LIBRARY_PATH", filepath.join(installDir, "lib"))!
os.setenv("DYLD_LIBRARY_PATH", filepath.join(installDir, "lib"))!
}
exec! binary, "--help"
}
4 changes: 4 additions & 0 deletions weisslj/cpp-optparse/versions.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"path": "weisslj/cpp-optparse",
"deps": {}
}
Loading